package com.example.demo;

import com.example.demo.component.StudentComponent;
import com.example.demo.component.UserComponent;
import com.example.demo.config.UserConfig;
import com.example.demo.controller.HController;
import com.example.demo.controller.HelloController;
import com.example.demo.model.Student;
import com.example.demo.repository.UserRepository;
import com.example.demo.service.UserService;
import lombok.val;
import org.apache.catalina.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

import java.util.concurrent.Callable;

@SpringBootApplication
public class SpringIocDemoApplication {

	public static void main(String[] args) {
		ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);

		// 五大注解 @Controller @Service @Repository @Configuration @Component
		// 其中另外四个都是基于 @Component 来管理对象的

		// 使用 @Controller 注解管理对象
		// 有三种方式
		// 方法1 通过对象名来拿到对象 这个对象名使用类名的小驼峰方式进行命名，并且需要强转，因为这样获取到的对象是 Object 类型
//		HelloController controllerBean1 = (HelloController) context.getBean("helloController");
//		controllerBean1.print();

		// 对于对象名，如果类名的前两个字母都是大写的话，那么对象名就和类名相同
		// 如果指定了对象名，那么就不能使用默认的对象名，就得使用指定的对象名
//		HController controllerBean2 = (HController) context.getBean("haha");
//		controllerBean2.print();

		// 方法2 通过类直接访问
//		HelloController controllerBean3 = context.getBean(HelloController.class);
//		controllerBean3.print();

		// 方法3 通过对象名和类名
//		HelloController controllerBean4 = context.getBean("helloController",HelloController.class);
//		controllerBean4.print();


		// 使用 @Service 注解管理对象
		// 与上面的方式一样，也有三种方法
//		UserService serviceBean1 = (UserService) context.getBean("userService");
//		serviceBean1.print();
//
//		UserService serviceBean2 = context.getBean(UserService.class);
//		serviceBean2.print();
//
//		UserService serviceBean3 = context.getBean("userService",UserService.class);
//		serviceBean3.print();


		// 使用 @Repository 注解管理对象
		// 与上面的方式一样，也有三种方法
//		UserRepository repositoryBean1 = (UserRepository) context.getBean("userRepository");
//		repositoryBean1.print();
//
//		UserRepository repositoryBean2 = context.getBean(UserRepository.class);
//		repositoryBean2.print();
//
//		UserRepository repositoryBean3 = context.getBean("userRepository",UserRepository.class);
//		repositoryBean3.print();


		// 使用 @Configuration 注解管理对象
		// 与上面的方式一样，也有三种方法
//		UserConfig configBean1 = (UserConfig) context.getBean("userConfig");
//		configBean1.print();
//
//		UserConfig configBean2 = context.getBean(UserConfig.class);
//		configBean2.print();
//
//		UserConfig configBean3 = context.getBean("userConfig",UserConfig.class);
//		configBean3.print();


		// 使用 @Component 注解管理对象
		// 与上面的方式一样，也有三种方法
//		UserComponent componentBean1 = (UserComponent) context.getBean("userComponent");
//		componentBean1.print();
//
//		UserComponent componentBean2 = context.getBean(UserComponent.class);
//		componentBean2.print();
//
//		UserComponent componentBean3 = context.getBean("userComponent",UserComponent.class);
//		componentBean3.print();


		// @Bean注解
		// 使用 Bean 注解需要搭配方法使用，也就是说在一个方法里new对象之后给这个方法加上 @Bean 注解
		// Student 示例
		// 对象名就是这个方法名
//		Student bean1 = (Student) context.getBean("s1");
//		System.out.println(bean1);

		// 这个也可以不是方法名，可以自己指定
//		Student bean2 = (Student) context.getBean("ha");
//		System.out.println(bean2);

		// 指定名字也可以是指定多个，也就是说可以通过多个名字来指向这个对象
//		Student bean3 = (Student) context.getBean("wang");
//		Student bean4 = (Student) context.getBean("wu");
//		System.out.println(bean3 + " " + bean4);

		// 也可以是名字由另外的方法指定，然后new对象的时候把这个名字给传进去
		// 但是这个时候要求只有一个名字为name的Bean，不然还是会报错
//		Student bean5 = (Student) context.getBean("s4");
//		System.out.println(bean5);


		// 依赖注入测试
//		HelloController bean = context.getBean(HelloController.class);
//		bean.print();

		// 如果有多个对象时怎么确定使用哪个对象
		// 有三种方法
		// 一 在对象前加上@Primary注解
		// 二 在要使用这个对象前加上@Qualifier注解，并指定对象名称
		// 三 在要使用这个对象前加上@Resource注解，并指定对象名称
		// 该部分代码在 UserService 中测试
//		UserService userService = context.getBean(UserService.class);
//		userService.print();
	}

}
